package com.ponhu.ea2.stockcenter.provider.schedule;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.ponhu.ea2.stockcenter.provider.constants.CommonConstant;
import com.ponhu.ea2.stockcenter.provider.support.service.RedisSupportService;
import com.ponhu.ea2.stockcenter.service.bms.StockCheckService;
import com.ponhu.ea2.stockcenter.service.bms.StockFixService;
import com.ponhu.ea2.stockcenter.vo.TemStockDifferenceVo;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 库存修复定时任务
 *
 * @author Wang
 * @date 2022/1/20 4:51 下午
 */
@Slf4j
@Component
public class StockFixDataTask {

    @Resource
    private StockFixService stockFixService;

    @Autowired
    private RedisSupportService redisSupportService;

    @Autowired
    private StockCheckService stockCheckService;

    /**
     * 全量修复销售订单状态（取消占用、销售出库状态）
     * 一次性任务
     */
    @XxlJob("fixAllInventoryDocOccupyDataTask")
    public void processDocOccupyFix() {
        stockFixService.fixAllInventoryDocOccupyData();
        stockFixService.fixAllPurchaseDocOccupyData();
    }

    /**
     * 定时修复货品库存数量：type 1-通过巨沃接口，2-通过巨沃数据库
     */
    @XxlJob("correctStockCronType1")
    public void correctStockCronType1() {
        correctStockCron(1);
    }

    /**
     * 定时修复货品库存数量：type 1-通过巨沃接口，2-通过巨沃数据库
     */
    @XxlJob("correctStockCronType2")
    public void correctStockCronType2() {
        correctStockCron(2);
    }

    /**
     * 定时修复货品库存数量：type 1-通过巨沃接口，2-通过巨沃数据库
     */
    public void correctStockCron(Integer type) {

        log.info("XXL-Job ===>> 定时修复货品库存数量 ===>> type={} ===>> 任务开始启动", type);

        Set<String> inventoryCodes = redisSupportService
                .rSetReadAll(CommonConstant.WMS_EVENT_HANDLER_ERROR, String.class);
        log.info("XXL-Job ===>> 定时修复货品库存数量 ===>> type={} ===>> 待修复货品编码：{} = {}",
                type, inventoryCodes.size(), inventoryCodes);
        if (CollectionUtils.isEmpty(inventoryCodes)) return;

        CompletableFuture.runAsync(() -> {
            log.info("XXL-Job ===>> 定时修复货品库存数量 ===>> type={} ===>> 开始执行", type);
            long start = System.currentTimeMillis();
            int batchSize = 1000;
            for (int i = 0; i <= inventoryCodes.size() / batchSize; i++) {
                List<String> bacthList = inventoryCodes.stream().skip(i * batchSize).limit(batchSize).collect(Collectors.toList());
                List<String> resList = stockCheckService.correctStockByInventoryCodes(bacthList, type).getData();
                log.info("XXL-Job ===>> 定时修复货品库存数量 ===>> type={} ===>> 分批执行完成：{} " +
                        "===>> 其中执行失败：{} = {}", type, bacthList.size(), resList.size(), resList);
            }
            log.info("XXL-Job ===>> 定时修复货品库存数量 ===>> type={} ===>> 执行完成 " +
                    "===>> 耗时：{}", type, System.currentTimeMillis() - start);

            redisSupportService.rSetDelete(CommonConstant.WMS_EVENT_HANDLER_ERROR, String.class);
        });

        XxlJobHelper.handleSuccess("XXL-Job ===>> 定时修复货品库存数量 ===>> 任务开始成功");
    }

    /**
     * 定时对比库存中心和巨沃货品库存数量：type 1-通过巨沃接口，2-通过巨沃数据库
     */
    @XxlJob("contrastStockCronType1")
    public void contrastStockCronType1(Integer type) {
        contrastStockCron(1);
    }

    /**
     * 定时对比库存中心和巨沃货品库存数量：type 1-通过巨沃接口，2-通过巨沃数据库
     */
    @XxlJob("contrastStockCronType2")
    public void contrastStockCronType2() {
        contrastStockCron(2);
    }

    /**
     * 定时对比库存中心和巨沃货品库存数量：type 1-通过巨沃接口，2-通过巨沃数据库
     */
    public void contrastStockCron(Integer type) {

        log.info("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> type={} ===>> 任务开始启动", type);

        CompletableFuture.runAsync(() -> {
            log.info("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> type={} ===>> 开始执行", type);

            redisSupportService.rSetDelete(CommonConstant.WMS_EVENT_HANDLER_ERROR, String.class);
            log.info("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> type={} ===>> 清除之前对比结果缓存", type);

            long start = System.currentTimeMillis();
            List<TemStockDifferenceVo> differenceVoList = stockCheckService.exportStockDifferenceVos(type).getData();
            log.info("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> type={},  ===>> 执行完成 " +
                    "===>> 耗时：{} ===>> 差异数量={}", type, System.currentTimeMillis() - start, differenceVoList.size());
            if (CollectionUtils.isEmpty(differenceVoList)) return;

            // 将库存差异货品编码缓存至Redis待定时任务执行库存修复
            Set<String> inventoryCodes = differenceVoList.parallelStream()
                    .filter(differenceVo -> !differenceVo.getWhHas().equals("商品系统不存在"))
//                    .filter(differenceVo -> differenceVo.getWhHas().equals("存在") && differenceVo.getJwHas().equals("存在"))
                    .map(TemStockDifferenceVo::getInventoryCode).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(inventoryCodes)) {
                redisSupportService.rSetAddAll(CommonConstant.WMS_EVENT_HANDLER_ERROR, inventoryCodes);
                log.info("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> type={} " +
                        "===>> 上传Redis缓存完成 ===>> {}", type, inventoryCodes);
            }

            // 生产库存差异文件并上传七牛云
            stockCheckService.diffUpload(differenceVoList);
            log.info("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> type={} ===>> 上传七牛云完成", type);
        });

        XxlJobHelper.handleSuccess("XXL-Job ===>> 定时对比库存中心和巨沃货品库存数量 ===>> 成功启动");
    }

}
